package com.zyfu.demo.function.function.bi_function;

import com.zyfu.demo.domain.User;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;

/**
 * <b>请输入名称</b>
 * <pre>
 * 描述<br/>
 * 作用：；<br/>
 * 限制：；<br/>
 * </pre>
 *
 * @author 张永福
 * @since 2024/2/28 23:12
 */
public class MapTest {

    /**
     * map的putIfAbsent理解：
     * java.util.Map#putIfAbsent(java.lang.Object, java.lang.Object)
     * absent：缺席，缺少的 ...
     * put if absent: 当没有指定的key时 则 put
     */
    @Test
    public void testMap_putIfAbsent() {
        Map<String, User> name2User = new HashMap<>();
        name2User.putIfAbsent("张三", User.builder().age(20).build());
        assert name2User.size() == 1;

        name2User.putIfAbsent("张三", User.builder().age(30).build());
        assert name2User.size() == 1;
        assert name2User.get("张三").getAge() == 20;
    }

    /**
     * map 的 computeIfAbsent 方法的理解：
     * java.util.Map#computeIfAbsent(K key, Function<? super K, ? extends V)
     * 注意：
     * 1. computeIfAbsent中的 Function 的执行前提是 key 不存在
     * 2. 通过查看源码，可以知道，如果Function的 apply方法执行结果为空时，不会put新的key值。
     * 即：computeIfAbsent不会塞 null 到value中; 这一点注意和 putIfAbsent方法做区分
     *
     */
    @Test
    public void testMap_computeIfAbsent() {
        Map<String, User> name2User = new HashMap<>();
        name2User.computeIfAbsent("张三", key -> User.builder().build());
        assert name2User.size() == 1;

        name2User.computeIfAbsent("李四", key -> null);
        assert name2User.size() == 1;

        name2User.putIfAbsent("李四", null);
        assert name2User.size() == 2;

    }

    /**
     * computeIfPresent 方法的理解：
     * java.util.Map#computeIfPresent(java.lang.Object, java.util.function.BiFunction<? super K, ? super V, ? extends V>)
     * present: 出席，在场，存在的 ...
     * compute if present:  map中已经存在某个key， 则执行某个计算。
     * BiFunction 是计算方法， BiFunction<T, U, R> 类名定义了三种类型,
     * apply 方法上  R apply(T t, U u);
     * 对比computeIfPresent方法签名上的 <? super K, ? super V, ? extends V>
     * computeIfPresent 中 BiFunction的 apply方法返回值类型 R 和 U 的类型是同一个类型， 对应为Map的value的类型
     * ---------------------------------------
     * 拓展：
     * ? super K
     * 解读：
     * super 是上界通配符
     * 未知类 ? 必须是 K 类型本身或者是K的超类
     * ? extends V
     * 解读：
     * extends 是下界通配符
     * 未知类 ? 必须是 K 类型本身或者是K的子类
     */
    @Test
    public void testMap_computeIfPresent() {
        Map<String, User> name2User = new HashMap<>();
        name2User.put("张三", User.builder().age(20).build());

        name2User.computeIfPresent("张三", (key, user) -> {
            user.setAge(30);
            return user;
        });
        assert name2User.get("张三").getAge() == 30;
    }



}
